package random

import (
	"math/rand"

	"gitee.com/liuxuezhan/ar-platform/assets-rpc/rpc"
	"github.com/jinzhu/copier"
	"github.com/shopspring/decimal"
	"google.golang.org/protobuf/encoding/protojson"
)

var ice, zero int32

const ice_max = 5 // 格子范围

func intit() {
	ice = -1                                        // 冰冻程度
	zero = int32(rpc.SlotGameSymbol_symbol_Default) // 没有冰
}
func SlotGameRand(in *rpc.SlotGameStartRes) (err error, out *rpc.SlotGameStartRes) {
	out = &rpc.SlotGameStartRes{}
	copier.Copy(out, in)
	err = protojson.Unmarshal([]byte(out.Save.Json_Bet_XY), out.GetBet_XY())
	if err != nil {
		return err, nil
	}
	out.Save.BetAmount, _ = decimal.NewFromFloat(out.Save.BetSize).
		Mul(decimal.NewFromInt32(out.Save.BetLevel)).
		Mul(decimal.NewFromFloat(out.Save.BaseBet)).Float64()
	out.GetBet_XY()
	if out.GetBet_XY() == nil {
		// 初始化位图
		Bet_init(out)
	}

	if out.GetBonus() != nil {
		// Bonus游戏
		if out.GetBonus().BonusRedNum > 0 {
			out.GetBonus().BonusRedNum--
		} else {
			out.Bonus = nil
			Bet_init(out)
		}
	}
	for _, v := range out.Bet_XY.GetOne() { // 随机
		if v.GetValue() >= 0 {
			v.Value = Int31n(len(rpc.SlotGameSymbol_value) - 1)

		}
	}
	out.SymbolPath = map[int32]*rpc.BetPath{}
	for _, v := range out.Bet_XY.GetOne() {
		// 计算连中
		if out.SymbolPath[v.GetValue()] == nil {
			out.SymbolPath[v.GetValue()] = &rpc.BetPath{Arr: map[int32]int32{}}
		}
		out.SymbolPath[v.GetValue()].Arr[int32(v.GetY())]++
	}

	for Symbol, path := range out.SymbolPath { // 计算赔率
		path.Count = 0
		count := decimal.NewFromFloat(1) // 总中奖路数
		for i := int32(1); i <= ice_max; i++ {
			if path.Arr[i] > 0 {
				path.Count++
				path.Count++
				count = count.Mul(decimal.NewFromInt32(path.Arr[i]))
			} else {
				count = decimal.NewFromFloat(1)
			}
		}
		if path.Count >= 3 {
			WinAmount := decimal.NewFromFloat(out.Save.BetSize).
				Mul(decimal.NewFromInt32(out.Save.BetLevel)).
				Mul(decimal.NewFromInt32(Symbol)). // 赔付比
				Mul(count)
			if out.GetBonus() != nil {
				WinAmount = WinAmount.Mul(decimal.NewFromInt32(out.GetBonus().BonusBlueNum))
				out.GetBonus().BonusRed++
				out.GetBonus().BonusBlue++
				if out.GetBonus().BonusRed >= 10 {
					out.GetBonus().BonusRedNum += out.GetBonus().BonusRed / 10
					out.GetBonus().BonusRed += out.GetBonus().BonusRed % 10
				}
				if out.GetBonus().BonusBlue >= 10 {
					out.GetBonus().BonusBlueNum += out.GetBonus().BonusBlue / 10
					out.GetBonus().BonusBlue += out.GetBonus().BonusBlue % 10
				}
			} else {
				out.Save.TotalAmount -= path.WinAmount
				IceRand(path.Count, out.Bet_XY.GetOne())
			}
			path.WinAmount, _ = WinAmount.Round(2).Float64()
			out.Save.WinAmount += path.WinAmount
		} else {
			delete(out.SymbolPath, Symbol)
		}
	}
	if IsBonus(out.Bet_XY.GetOne()) && out.GetBonus() == nil {
		out.Bonus = &rpc.Bonus{
			BonusRedNum:  1,
			BonusBlueNum: 2,
		}
	}
	out.Save.TotalAmount -= out.Save.BetAmount
	jsonBytes, _ := protojson.Marshal(out.GetBet_XY())
	out.Save.Json_Bet_XY = string(jsonBytes)
	return
}
func Bet_init(out *rpc.SlotGameStartRes) {
	out.Bet_XY = &rpc.XYs{One: []*rpc.XY{}}
	for y := uint32(1); y <= ice_max; y++ {
		for x := uint32(1); x <= ice_max; x++ {
			switch {
			case x == 1 && y == 1,
				x == ice_max && y == 1,
				x == 1 && y == ice_max,
				x == ice_max && y == ice_max:
				out.Bet_XY.One = append(out.Bet_XY.GetOne(), &rpc.XY{X: x, Y: y, Value: ice - 2})
			case x == 2 && y == 1, x == 1 && y == 2,
				x == ice_max-1 && y == 1, x == ice_max && y == 2,
				x == 1 && y == ice_max-1, x == 2 && y == ice_max,
				x == ice_max-1 && y == ice_max, x == ice_max && y == ice_max-1:
				out.Bet_XY.One = append(out.Bet_XY.GetOne(), &rpc.XY{X: x, Y: y, Value: ice})
			default:
				out.Bet_XY.One = append(out.Bet_XY.GetOne(), &rpc.XY{X: x, Y: y, Value: zero})
			}

		}
	}
}
func IsBonus(arr []*rpc.XY) bool { // 进入Bonus游戏
	for _, xy := range arr {
		if xy.GetValue() <= zero {
			return false
		}
	}
	return true
}
func IceRand(count int32, arr []*rpc.XY) { // 随机破冰
	arr1 := []*rpc.XY{}
	arr2 := []*rpc.XY{}
	for _, xy := range arr {
		if xy.GetValue() <= zero {
			switch {
			case xy.GetX() == 1 && xy.GetY() == 1,
				xy.GetX() == ice_max && xy.GetY() == 1,
				xy.GetX() == 1 && xy.GetY() == ice_max,
				xy.GetX() == ice_max && xy.GetY() == ice_max:
				arr1 = append(arr1, xy)
			default:
				arr2 = append(arr2, xy)
			}
		}

	}
	rand.Shuffle(len(arr1), func(i, j int) {
		arr1[i], arr1[j] = arr1[j], arr1[i]
	})
	rand.Shuffle(len(arr2), func(i, j int) {
		arr2[i], arr2[j] = arr2[j], arr2[i]
	})
	for _, xy := range arr2 {
		if count > 0 {
			xy.Value += 1
			count--
		}
	}

	for _, xy := range arr1 {
		if count > 0 {
			xy.Value += 1
			count--
		}
	}
}
